using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

// ~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~

// All added functionality is enclosed in commented flags such as:
// -------------------------ADDED FOR MORE FUNCTIONALITY--------------------
// ADDED FUNCTIONALITY..........
// -------------------------END OF ADDED FUNCTIONALITY------------------------

// I have expanded the functionality of the InputHandler class so that you can now bind a button, key, or
// mouse button with a certain state under the "ButtonStateLogic" enum.  This will allow you to run a method
// under more precise conditions than just under a button/key press.  This will let you to take action when you
// release a button/key, the button/key is being held (the old and new states of the button/key are both pressed), 
// as well as taking action when a button ISN'T being pressed.

// I have also expanded the functionality of the InputHandler class for more precise mouse and joystick movements.
// Rather than executing a method WHENEVER the mouse or joysticks is moved, the method will only run if the joystick/mouse
// is moving in a certain direction.  This way you could have a method that scrolls the screen up, bind that method 
// with the action of the mouse moving up, and will not have to determine within the scrolling method which direction
// the mouse/joystick is moving.  This analog directions can be bound to any method and be used for any behaviour desired.

// ~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~REVISED~~

namespace Campus
{
    #region Namespace type definitions
    public enum MouseButtons { LeftButton, MiddleButton, RightButton, XButton1, XButton2, None };
    public enum MouseAnalogs { Pointer, ScrollWheel };
    // Deleted the 'Right Trigger' and 'Left Trigger' from the GamePadAnalogs enum as they are already included
    // under 'Buttons.'  If you don't like it, bite me.
    public enum GamePadAnalogs { LeftStick, RightStick };
    // ----------------ADDED FOR MORE FUNCTIONALITY----------------------
    public enum AnalogMovements { MoveLeft, MoveRight, MoveUp, MoveDown };
    public enum ButtonStateLogic { Pressed, Released, Held, NotPressed };
    // ------------------END OF ADDED FUNCTIONALITY------------------------

    #endregion

    public class InputHandler {

        #region Type Definitions
        /// <summary>/// The delegate function signature that is used for all Button mappings
        /// <param name="button">The button that was activated</param>
        /// <param name="state">The state of the Button (pressed orreleased)</param>
        /// <param name="index">The player index of the gamepad</param>
        /// </summary>
        public delegate void ButtonInputAction(Buttons button, ButtonState state, PlayerIndex index);

        /// <summary>
        /// The delegate function signature that is used for allGamePad Thumbstick/Trigger mappings
        /// <param name="x">The "X" value of the GamePad thumbstickcontrol</param>
        /// <param name="y">The "Y" value of the GamePad thumbstickcontrol</param>
        /// <param name="control">Which control is active</param>
        /// <param name="index">The player index of the gamepad</param>
        /// </summary>
        public delegate void GamePadInputAction(GamePadAnalogs control, float x, float y, PlayerIndex index);

        /// <summary>
        /// The delegate function signature that is used for all Mouse mappings
        /// <param name="control"> The control that is active</param>
        /// <param name="x">The "X" value of the mouse control (always 0 for the scrollwheel)</param>
        /// <param name="y">The "Y" value of the mouse control</param>
        /// </summary>
        public delegate void MouseInputAction(MouseAnalogs control, int x, int y);

        /// <summary>
        /// The delegate function signature that is used for all Key mappings
        /// <param name="key">The key that was pressed</param>
        /// <param name="state">The state of the Key</param>
        /// </summary>
        public delegate void KeyInputAction(Keys key, KeyState state);

        /// <summary>
        /// The delegate function signature that is used for all mouse button mappings
        /// <param name="button">The mouse button that was pressed</param>
        /// <param name="state">The state of the mouse button</param>
        /// </summary>
        public delegate void MouseButtonInputAction(MouseButtons button, ButtonState state);

        // ------------------------ADDED FOR MORE FUNCTIONALITY------------------------
        /// <summary>
        /// The delegate function signature that is used for functions requiring more knowledge
        /// about the state of the button.
        /// <param name="button">The mouse button that was pressed</param>
        /// <param name="state">The state the button is in</param>
        /// </summary>
        public delegate void MouseButtonLogicAction(MouseButtons button, ButtonStateLogic state);

        /// <summary>
        /// The delegate function signature that is used for functions requiring more knowledge
        /// about the state of the key.
        /// <param name="button">The key that was pressed</param>
        /// <param name="state">The state the key is in</param>
        /// </summary>
        public delegate void KeyLogicAction(Keys key, ButtonStateLogic state);

        /// <summary>/// The delegate function signature that is used for all Button mappings
        /// <param name="button">The button that was activated</param>
        /// <param name="state">The state of the Button (pressed orreleased)</param>
        /// <param name="index">The player index of the gamepad</param>
        /// </summary>
        public delegate void ButtonLogicAction(Buttons button, ButtonStateLogic state, PlayerIndex index);

        /// <summary>
        /// The delegate function signature that is used for all Mouse mappings
        /// <param name="movement">The direction the mouse has moved</param>
        /// <param name="x">The "X" value of the mouse control (always 0 for the scrollwheel)</param>
        /// <param name="y">The "Y" value of the mouse control</param>
        /// </summary>
        public delegate void MouseMovementAction(AnalogMovements movement, int x, int y);

        /// <summary>
        /// The delegate function signature that is used for allGamePad Thumbstick/Trigger mappings
        /// <param name="x">The "X" value of the GamePad thumbstickcontrol</param>
        /// <param name="movement">The direction the joystick has moved</param>
        /// <param name="y">The "Y" value of the GamePad thumbstickcontrol</param>
        /// <param name="control">Which control is active</param>
        /// <param name="index">The player index of the gamepad</param>
        /// </summary>
        public delegate void GamePadMovementAction(GamePadAnalogs control, AnalogMovements movement, 
                                                   float x, float y, PlayerIndex index);
        struct KeyDelegateLogic
        {
            public KeyDelegateLogic(Keys akey, ButtonStateLogic alogic, KeyLogicAction aaction)
            {
                key = akey;
                logic = alogic;
                action = aaction;
            }
            public Keys key;
            public ButtonStateLogic logic;
            public KeyLogicAction action;
        }
        struct ButtonDelegateLogic
        {
            public ButtonDelegateLogic(Buttons abutton, ButtonStateLogic alogic, ButtonLogicAction aaction)
            {
                button = abutton;
                logic = alogic;
                action = aaction;
            }
            public Buttons button;
            public ButtonStateLogic logic;
            public ButtonLogicAction action;
        }
        struct MouseButtonDelegateLogic
        {
            public MouseButtonDelegateLogic(MouseButtons abutton,
                ButtonStateLogic alogic, MouseButtonLogicAction aaction)
            {
                button = abutton;
                logic = alogic;
                action = aaction;
            }
            public MouseButtons button;
            public ButtonStateLogic logic;
            public MouseButtonLogicAction action;
        }
        struct MouseMovementDelegateLogic
        {
            public MouseMovementDelegateLogic(AnalogMovements amovement, MouseMovementAction aaction)
            {
                movement = amovement;
                action = aaction;
            }
            public AnalogMovements movement;
            public MouseMovementAction action;
        }
        struct JoystickMovementDelegateLogic
        {
            public JoystickMovementDelegateLogic(GamePadAnalogs ajoystick, 
                AnalogMovements amovement, GamePadMovementAction aaction)
            {
                joystick = ajoystick;
                movement = amovement;
                action = aaction;
            }
            public GamePadAnalogs joystick;
            public AnalogMovements movement;
            public GamePadMovementAction action;
        }
        // ----------------END OF ADDED FUNCTIONALITY----------------------
        #endregion

        #region Fields
        private KeyboardState m_oldKeyboard = Keyboard.GetState();
        private MouseState m_oldMouse = Mouse.GetState();
        private GamePadState m_oldGamePad = GamePad.GetState(PlayerIndex.One);
        private GamePadState m_oldGamePad2 = GamePad.GetState(PlayerIndex.Two);
        private GamePadState m_oldGamePad3 = GamePad.GetState(PlayerIndex.Three);
        private GamePadState m_oldGamePad4 = GamePad.GetState(PlayerIndex.Four);

        //Lists for holding all the bindings
        private List<KeyValuePair<Buttons, ButtonInputAction>> m_gamePadBindings;
        private List<KeyValuePair<Keys, KeyInputAction>> m_keyboardBindings;
        private List<KeyValuePair<MouseButtons, MouseButtonInputAction>> m_mouseBindings;
        private List<KeyValuePair<MouseAnalogs, MouseInputAction>> m_mouseAnalogBindings;
        private List<KeyValuePair<GamePadAnalogs, GamePadInputAction>> m_gamePadAnalogBindings;

        // ------------------------ADDED FOR MORE FUNCTIONALITY-------------------
        private List<JoystickMovementDelegateLogic> m_gamePadMovementBindings;
        private List<MouseMovementDelegateLogic> m_mouseMovementBindings;
        private List<ButtonDelegateLogic> m_gamePadLogicBindings;
        private List<MouseButtonDelegateLogic> m_mouseButtonLogicBindings;
        private List<KeyDelegateLogic> m_keyboardLogicBindings;
        // ----------------END OF ADDED FUNCTIONALITY----------------------
        #endregion

        #region Other Functions

        /// <summary>
        /// The constructor for this class (needed to instantiate the lists for the bindings)
        /// </summary>
        public InputHandler()
        {
            m_gamePadBindings = new List<KeyValuePair<Buttons, ButtonInputAction>>();
            m_keyboardBindings = new List<KeyValuePair<Keys, KeyInputAction>>();
            m_mouseBindings = new List<KeyValuePair<MouseButtons, MouseButtonInputAction>>();
            m_mouseAnalogBindings = new List<KeyValuePair<MouseAnalogs, MouseInputAction>>();
            m_gamePadAnalogBindings = new List<KeyValuePair<GamePadAnalogs, GamePadInputAction>>();

            // ----------------------ADDED FOR MORE FUNCTIONALITY---------------------
            m_gamePadMovementBindings = new List<JoystickMovementDelegateLogic>();
            m_mouseMovementBindings = new List<MouseMovementDelegateLogic>();
            m_gamePadLogicBindings = new List<ButtonDelegateLogic>();
            m_keyboardLogicBindings = new List<KeyDelegateLogic>();
            m_mouseButtonLogicBindings = new List<MouseButtonDelegateLogic>();
            // ----------------END OF ADDED FUNCTIONALITY----------------------
        }

        /// <summary>
        /// Bind a gamepad button to an action
        /// <param name="button">the button to associate with an action</param>
        /// <param name="action">The action to take when this button is pressed</param>
        /// <param name="flag">0 to overwrite, 1 to append a binding</param>
        /// </summary>
        public void Bind(Buttons button, ButtonInputAction action, int flag)
        {
            if (flag == 0)
            {
                List<KeyValuePair<Buttons, ButtonInputAction>> removeList = 
                    new List<KeyValuePair<Buttons, ButtonInputAction>>();
                // Adds all the key/value pairs that contain that button to the remove list.
                foreach(KeyValuePair<Buttons, ButtonInputAction> pair in m_gamePadBindings)
                {
                    if (pair.Key == button)
                    {
                        removeList.Add(pair);
                    }
                }
                // Removes all the pairs targeted to be unbinded.
                foreach(KeyValuePair<Buttons, ButtonInputAction> pair in removeList)
                {
                    m_gamePadBindings.Remove(pair);
                }
            }
            m_gamePadBindings.Add(new KeyValuePair<Buttons, ButtonInputAction>(button, action));
        }

        /// <summary>
        /// Bind a keyboard key to an action
        /// <param name="button">the button to associate with an action</param>
        /// <param name="action">The action to take when this button is pressed</param>
        /// <param name="flag">0 to overwrite, 1 to append a binding</param>
        /// </summary>
        public void Bind(Keys button, KeyInputAction action, int flag)
        {
            if (flag == 0)
            {
                List<KeyValuePair<Keys, KeyInputAction>> removeList =
                    new List<KeyValuePair<Keys, KeyInputAction>>();
                // Adds all the key/value pairs that contain that button to the remove list.
                foreach (KeyValuePair<Keys, KeyInputAction> pair in m_keyboardBindings)
                {
                    if (pair.Key == button)
                    {
                        removeList.Add(pair);
                    }
                }
                // Removes all the pairs targeted to be unbinded.
                foreach (KeyValuePair<Keys, KeyInputAction> pair in removeList)
                {
                    m_keyboardBindings.Remove(pair);
                }
            }
            m_keyboardBindings.Add(new KeyValuePair<Keys, KeyInputAction>(button, action));
        }

        /// <summary>
        /// Bind a mouse button to an action
        /// <param name="button">the button to associate with an action</param>
        /// <param name="action">The action to take when this button is pressed</param>
        /// <param name="flag">0 to overwite binding, 1 to append a binding</param>
        /// </summary>
        public void Bind(MouseButtons button, MouseButtonInputAction action, int flag) 
        {
            if (flag == 0)
            {
                List<KeyValuePair<MouseButtons, MouseButtonInputAction>> removeList =
                    new List<KeyValuePair<MouseButtons, MouseButtonInputAction>>();
                // Adds all the key/value pairs that contain that button to the remove list.
                foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in m_mouseBindings)
                {
                    if (pair.Key == button)
                    {
                        removeList.Add(pair);
                    }
                }
                // Removes all the pairs targeted to be unbinded.
                foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in removeList)
                {
                    m_mouseBindings.Remove(pair);
                }
            }
            m_mouseBindings.Add(new KeyValuePair<MouseButtons, MouseButtonInputAction>(button, action));
        }

        // ---------------ADDED FOR MORE FUNCTIONALITY-----------------
        /// <summary>
        /// Bind a mouse button with the extended logic state.
        /// <param name="button">The button to bind</param>
        /// <param name="logic">The state the button should be in so the delegate is invoked</param>
        /// <param name="action">The action to bind</param>
        /// <param name="flag">0 to overwrite binding, 1 to append a binding</param>
        /// </summary>
        public void Bind(MouseButtons newButton, ButtonStateLogic newLogic, MouseButtonLogicAction newAction, int flag)
        {
            if (flag == 0)
            {
                List<MouseButtonDelegateLogic> removeList = new List<MouseButtonDelegateLogic>();
                foreach (MouseButtonDelegateLogic binding in m_mouseButtonLogicBindings)
                {
                    if (binding.button == newButton && binding.logic == newLogic && binding.action == newAction)
                    {
                        removeList.Add(binding);
                    }
                }

                foreach (MouseButtonDelegateLogic binding in removeList)
                {
                    m_mouseButtonLogicBindings.Remove(binding);
                }
            }
            m_mouseButtonLogicBindings.Add(new MouseButtonDelegateLogic(newButton, newLogic, newAction));
        }

        /// <summary>
        /// Bind a gamepad button with the extended logic state.
        /// <param name="button">The button to bind</param>
        /// <param name="logic">The state the button should be in so the delegate is invoked</param>
        /// <param name="action">The action to bind</param>
        /// <param name="flag">0 to overwrite binding, 1 to append a binding</param>
        /// </summary>
        public void Bind(Buttons newButton, ButtonStateLogic newLogic, ButtonLogicAction newAction, int flag)
        {
            if (flag == 0)
            {
                List<ButtonDelegateLogic> removeList = new List<ButtonDelegateLogic>();
                foreach (ButtonDelegateLogic binding in m_gamePadLogicBindings)
                {
                    if (binding.button == newButton && binding.logic == newLogic && binding.action == newAction)
                    {
                        removeList.Add(binding);
                    }
                }

                foreach (ButtonDelegateLogic binding in removeList)
                {
                    m_gamePadLogicBindings.Remove(binding);
                }
            }
            m_gamePadLogicBindings.Add(new ButtonDelegateLogic(newButton, newLogic, newAction));
        }

        /// <summary>
        /// Bind a keyboard key with the extended logic state.
        /// <param name="button">The key to bind</param>
        /// <param name="logic">The state the key should be in so the delegate is invoked</param>
        /// <param name="action">The action to bind</param>
        /// <param name="flag">0 to overwrite binding, 1 to append a binding</param>
        /// </summary>
        public void Bind(Keys newKey, ButtonStateLogic newLogic, KeyLogicAction newAction, int flag)
        {
            if (flag == 0)
            {
                List<KeyDelegateLogic> removeList = new List<KeyDelegateLogic>();
                foreach (KeyDelegateLogic binding in m_keyboardLogicBindings)
                {
                    if (binding.key == newKey && binding.logic == newLogic && binding.action == newAction)
                    {
                        removeList.Add(binding);
                    }
                }

                foreach (KeyDelegateLogic binding in removeList)
                {
                    m_keyboardLogicBindings.Remove(binding);
                }
            }
            m_keyboardLogicBindings.Add(new KeyDelegateLogic(newKey, newLogic, newAction));
        }

        /// <summary>
        /// Unbind a mouse button
        /// <param name="button">The button to unbind</param>
        /// </summary>
        public void UnbindLogic(MouseButtons oldButton)
        {
            List<MouseButtonDelegateLogic> removeList = new List<MouseButtonDelegateLogic>();
            foreach (MouseButtonDelegateLogic binding in m_mouseButtonLogicBindings)
            {
                if (binding.button == oldButton)
                {
                    removeList.Add(binding);
                }
            }

            foreach (MouseButtonDelegateLogic binding in removeList)
            {
                m_mouseButtonLogicBindings.Remove(binding);
            }
        }

        /// <summary>
        /// Unbind a gamepad button
        /// <param name="button">The button to unbind</param>
        /// </summary>
        public void UnbindLogic(Buttons oldButton)
        {
            List<ButtonDelegateLogic> removeList = new List<ButtonDelegateLogic>();
            foreach (ButtonDelegateLogic binding in m_gamePadLogicBindings)
            {
                if (binding.button == oldButton)
                {
                    removeList.Add(binding);
                }
            }

            foreach (ButtonDelegateLogic binding in removeList)
            {
                m_gamePadLogicBindings.Remove(binding);
            }
        }

        /// <summary>
        /// Unbind a keyboard key
        /// <param name="button">The key to unbind</param>
        /// </summary>
        public void UnbindLogic(Keys oldKey)
        {
            List<KeyDelegateLogic> removeList = new List<KeyDelegateLogic>();
            foreach (KeyDelegateLogic binding in m_keyboardLogicBindings)
            {
                if (binding.key == oldKey)
                {
                    removeList.Add(binding);
                }
            }

            foreach (KeyDelegateLogic binding in removeList)
            {
                m_keyboardLogicBindings.Remove(binding);
            }
        }
        // ----------------END OF ADDED FUNCTIONALITY----------------------
        /// <summary>
        /// Unbind a gamepad button
        /// <param name="button">The button to unbind</param>
        /// <param name="action">The action to unbind</param>
        /// </summary>
        public void Unbind(Buttons button, ButtonInputAction action)
        {
            List<KeyValuePair<Buttons, ButtonInputAction>> removeList =
                    new List<KeyValuePair<Buttons, ButtonInputAction>>();
            // Adds all the key/value pairs that contain that button to the remove list.
            foreach (KeyValuePair<Buttons, ButtonInputAction> pair in m_gamePadBindings)
            {
                if (pair.Key == button && pair.Value == action)
                {
                    removeList.Add(pair);
                }
            }
            // Removes all the pairs targeted to be unbinded.
            foreach (KeyValuePair<Buttons, ButtonInputAction> pair in removeList)
            {
                m_gamePadBindings.Remove(pair);
            }
        }

        /// <summary>
        /// Unbind a keyboard key
        /// <param name="button">The button to unbind</param>
        /// <param name="action">The action to unbind</param>
        /// </summary>
        public void Unbind(Keys button, KeyInputAction action)
        {
            List<KeyValuePair<Keys, KeyInputAction>> removeList =
                    new List<KeyValuePair<Keys, KeyInputAction>>();
            // Adds all the key/value pairs that contain that button to the remove list.
            foreach (KeyValuePair<Keys, KeyInputAction> pair in m_keyboardBindings)
            {
                if (pair.Key == button && pair.Value == action)
                {
                    removeList.Add(pair);
                }
            }
            // Removes all the pairs targeted to be unbinded.
            foreach (KeyValuePair<Keys, KeyInputAction> pair in removeList)
            {
                m_keyboardBindings.Remove(pair);
            }
        }

        /// <summary>
        /// Unbind a mouse button
        /// <param name="button">The button to unbind</param>
        /// <param name="action">The action to unbind</param>
        /// </summary>
        public void Unbind(MouseButtons button, MouseButtonInputAction action)
        {
            List<KeyValuePair<MouseButtons, MouseButtonInputAction>> removeList =
                    new List<KeyValuePair<MouseButtons, MouseButtonInputAction>>();
            // Adds all the key/value pairs that contain that button to the remove list.
            foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in m_mouseBindings)
            {
                if (pair.Key == button && pair.Value == action)
                {
                    removeList.Add(pair);
                }
            }
            // Removes all the pairs targeted to be unbinded.
            foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in removeList)
            {
                m_mouseBindings.Remove(pair);
            }
        }

        /// <summary>
        /// Bind gamepad analog joystick to an action
        /// <param name="control">The analog control to associate with an action</param>
        /// <param name="action">The action to take when this analog control changes</param>
        /// </summary>
        public void BindAnalog(GamePadAnalogs control, GamePadInputAction action)
        {
            m_gamePadAnalogBindings.Add(new KeyValuePair<GamePadAnalogs, GamePadInputAction>(control, action));
        }

        /// <summary>
        /// Bind mouse movement to an action
        /// <param name="control">The analog control to associate with an action</param>
        /// <param name="action">The action to take when this analog control changes</param>
        /// </summary>
        public void BindAnalog(MouseAnalogs control, MouseInputAction action)
        {
            m_mouseAnalogBindings.Add(new KeyValuePair<MouseAnalogs, MouseInputAction>(control, action));
        }

        // --------------------ADDED FOR MORE FUNCTIONALITY--------------------
        /// <summary>
        /// Bind gamepad analog joystick to an action
        /// <param name="control">The analog control to associate with an action</param>
        /// <param name="movement">The direction the joystick should be in for the delegate to be invoked</param>
        /// <param name="action">The action to take when this analog control changes</param>
        /// </summary>
        public void BindGamePadAnalogLogic(GamePadAnalogs control, AnalogMovements movement, GamePadMovementAction action)
        {
            m_gamePadMovementBindings.Add(new JoystickMovementDelegateLogic(control, movement, action));
        }

        /// <summary>
        /// Bind mouse analog movement to an action
        /// <param name="movement">The direction the mouse should move for the delegate to be invoked</param>
        /// <param name="action">The action to take when this movement is seen</param>
        /// </summary>
        public void BindMouseAnalogLogic(AnalogMovements movement, MouseMovementAction action)
        {
            m_mouseMovementBindings.Add(new MouseMovementDelegateLogic(movement, action));
        }

        /// <summary>
        /// Unbind a gamepad analog joystick movement
        /// <param name="control">The analog control to unbind</param>
        /// </summary>
        public void UnbindGamePadAnalogLogic(GamePadAnalogs oldJoystick)
        {
            List<JoystickMovementDelegateLogic> removeList = new List<JoystickMovementDelegateLogic>();

            foreach (JoystickMovementDelegateLogic binding in m_gamePadMovementBindings)
            {
                if (binding.joystick == oldJoystick)
                {
                    removeList.Add(binding);
                }
            }

            foreach (JoystickMovementDelegateLogic binding in removeList)
            {
                m_gamePadMovementBindings.Remove(binding);
            }
        }

        /// <summary>
        /// Unbind mouse analog movement to an action
        /// <param name="movement">The direction the mouse that should be unbinded</param>
        /// </summary>
        public void UnbindMouseAnalogLogic(AnalogMovements oldMovement)
        {
            List<MouseMovementDelegateLogic> removeList = new List<MouseMovementDelegateLogic>();

            foreach (MouseMovementDelegateLogic binding in m_mouseMovementBindings)
            {
                if (binding.movement == oldMovement)
                {
                    removeList.Add(binding);
                }
            }

            foreach (MouseMovementDelegateLogic binding in removeList)
            {
                m_mouseMovementBindings.Remove(binding);
            }
        }
        // --------------------END OF ADDED FUNCTIONALITY----------------------------

        /// <summary>
        /// Unbind a gamepad analog joystick movement
        /// <param name="control">The analog control to unbind</param>
        /// <param name="action">The action to unbind</param>
        /// </summary>
        public void UnbindAnalog(GamePadAnalogs control, GamePadInputAction action)
        {
            List<KeyValuePair<GamePadAnalogs, GamePadInputAction>> removeList =
                new List<KeyValuePair<GamePadAnalogs, GamePadInputAction>>();

            foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in m_gamePadAnalogBindings)
            {
                if (pair.Key == control && pair.Value == action)
                {
                    removeList.Add(pair);
                }
            }

            foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in removeList)
            {
                m_gamePadAnalogBindings.Remove(pair);
            }
        }

        /// <summary>
        /// Unbind the mouse movement
        /// <param name="control">The analog control to unbind</param>
        /// <param name="action">The action to unbind</param>
        /// </summary>
        public void UnbindAnalog(MouseAnalogs control, MouseInputAction action)
        {
            List<KeyValuePair<MouseAnalogs, MouseInputAction>> removeList =
                new List<KeyValuePair<MouseAnalogs, MouseInputAction>>();

            foreach (KeyValuePair<MouseAnalogs, MouseInputAction> pair in m_mouseAnalogBindings)
            {
                if (pair.Key == control && pair.Value == action)
                {
                    removeList.Add(pair);
                }
            }

            foreach (KeyValuePair<MouseAnalogs, MouseInputAction> pair in removeList)
            {
                m_mouseAnalogBindings.Remove(pair);
            }
        }

        /// <summary>
        /// The engine's update function should call this function which will check all inputs for changes
        /// </summary>
        public void CheckInputs() 
        {
            KeyboardState newKeyboard = Keyboard.GetState();
            MouseState newMouse = Mouse.GetState();
            GamePadState newGamePad1 = GamePad.GetState(PlayerIndex.One);
            GamePadState newGamePad2 = GamePad.GetState(PlayerIndex.Two);
            GamePadState newGamePad3 = GamePad.GetState(PlayerIndex.Three);
            GamePadState newGamePad4 = GamePad.GetState(PlayerIndex.Four);



            foreach (KeyValuePair<Keys, KeyInputAction> pair in m_keyboardBindings)
            {
                if (newKeyboard.IsKeyDown(pair.Key) && m_oldKeyboard.IsKeyUp(pair.Key))
                {
                    pair.Value.Invoke(pair.Key, KeyState.Down);
                }
            }

            foreach (KeyValuePair<Buttons, ButtonInputAction> pair in m_gamePadBindings)
            {
                if (newGamePad1.IsButtonDown(pair.Key) && m_oldGamePad.IsButtonUp(pair.Key))
                {
                    pair.Value.Invoke(pair.Key, ButtonState.Pressed, PlayerIndex.One);
                }
            }

            foreach (KeyValuePair<Buttons, ButtonInputAction> pair in m_gamePadBindings)
            {
                if (newGamePad2.IsButtonDown(pair.Key) && m_oldGamePad.IsButtonUp(pair.Key))
                {
                    pair.Value.Invoke(pair.Key, ButtonState.Pressed, PlayerIndex.Two);
                }
            }

            if (newMouse.LeftButton == ButtonState.Pressed && m_oldMouse.LeftButton == ButtonState.Released)
            {
                foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in m_mouseBindings)
                {
                    if (pair.Key == MouseButtons.LeftButton)
                    {
                        pair.Value.Invoke(MouseButtons.LeftButton, ButtonState.Pressed);
                    }
                }
            }

            if (newMouse.MiddleButton == ButtonState.Pressed && m_oldMouse.MiddleButton == ButtonState.Released)
            {
                foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in m_mouseBindings)
                {
                    if (pair.Key == MouseButtons.MiddleButton)
                    {
                        pair.Value.Invoke(MouseButtons.MiddleButton, ButtonState.Pressed);
                    }
                }
            }

            if (newMouse.RightButton == ButtonState.Pressed && m_oldMouse.RightButton == ButtonState.Released)
            {
                foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in m_mouseBindings)
                {
                    if (pair.Key == MouseButtons.RightButton)
                    {
                        pair.Value.Invoke(MouseButtons.RightButton, ButtonState.Pressed);
                    }
                }
            }

            if (newMouse.XButton1 == ButtonState.Pressed && m_oldMouse.XButton1 == ButtonState.Released)
            {
                foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in m_mouseBindings)
                {
                    if (pair.Key == MouseButtons.XButton1)
                    {
                        pair.Value.Invoke(MouseButtons.XButton1, ButtonState.Pressed);
                    }
                }
            }

            if (newMouse.XButton2 == ButtonState.Pressed && m_oldMouse.XButton2 == ButtonState.Released)
            {
                foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in m_mouseBindings)
                {
                    if (pair.Key == MouseButtons.XButton2)
                    {
                        pair.Value.Invoke(MouseButtons.XButton2, ButtonState.Pressed);
                    }
                }
            }

            // Determines whether no buttons are pressed, needed for the 'none' value in the MouseButtons enum.
            if (newMouse.LeftButton == ButtonState.Released && newMouse.MiddleButton == ButtonState.Released &&
                newMouse.RightButton == ButtonState.Released && newMouse.XButton1 == ButtonState.Released &&
                newMouse.XButton2 == ButtonState.Released)
            {
                foreach (KeyValuePair<MouseButtons, MouseButtonInputAction> pair in m_mouseBindings)
                {
                    if (pair.Key == MouseButtons.None)
                    {
                        pair.Value.Invoke(MouseButtons.None, ButtonState.Pressed);
                    }
                }
            }

            if (newMouse.X != m_oldMouse.X || newMouse.Y != m_oldMouse.Y)
            {
                foreach (KeyValuePair<MouseAnalogs, MouseInputAction> pair in m_mouseAnalogBindings)
                {
                    if (pair.Key == MouseAnalogs.Pointer)
                    {
                        pair.Value.Invoke(MouseAnalogs.Pointer, newMouse.X, newMouse.Y);
                    }
                }
            }

            if (newMouse.ScrollWheelValue != m_oldMouse.ScrollWheelValue)
            {
                foreach (KeyValuePair<MouseAnalogs, MouseInputAction> pair in m_mouseAnalogBindings)
                {
                    if (pair.Key == MouseAnalogs.ScrollWheel)
                    {
                        pair.Value.Invoke(MouseAnalogs.ScrollWheel, 0, newMouse.ScrollWheelValue);
                    }
                }
            }

            if (newGamePad1.ThumbSticks.Left.X != m_oldGamePad.ThumbSticks.Left.X ||
                newGamePad1.ThumbSticks.Left.Y != m_oldGamePad.ThumbSticks.Left.Y)
            {
                foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in m_gamePadAnalogBindings)
                {
                    if (pair.Key == GamePadAnalogs.LeftStick)
                    {
                        pair.Value.Invoke(GamePadAnalogs.LeftStick,
                            newGamePad1.ThumbSticks.Left.X, newGamePad1.ThumbSticks.Left.Y, PlayerIndex.One);
                    }
                }
            }

            if (newGamePad2.ThumbSticks.Left.X != m_oldGamePad.ThumbSticks.Left.X ||
                newGamePad2.ThumbSticks.Left.Y != m_oldGamePad.ThumbSticks.Left.Y)
            {
                foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in m_gamePadAnalogBindings)
                {
                    if (pair.Key == GamePadAnalogs.LeftStick)
                    {
                        pair.Value.Invoke(GamePadAnalogs.LeftStick,
                            newGamePad2.ThumbSticks.Left.X, newGamePad2.ThumbSticks.Left.Y, PlayerIndex.Two);
                    }
                }
            }

            if (newGamePad3.ThumbSticks.Left.X != m_oldGamePad.ThumbSticks.Left.X ||
                newGamePad3.ThumbSticks.Left.Y != m_oldGamePad.ThumbSticks.Left.Y)
            {
                foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in m_gamePadAnalogBindings)
                {
                    if (pair.Key == GamePadAnalogs.LeftStick)
                    {
                        pair.Value.Invoke(GamePadAnalogs.LeftStick,
                            newGamePad3.ThumbSticks.Left.X, newGamePad3.ThumbSticks.Left.Y, PlayerIndex.Three);
                    }
                }
            }

            if (newGamePad4.ThumbSticks.Left.X != m_oldGamePad.ThumbSticks.Left.X ||
                newGamePad4.ThumbSticks.Left.Y != m_oldGamePad.ThumbSticks.Left.Y)
            {
                foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in m_gamePadAnalogBindings)
                {
                    if (pair.Key == GamePadAnalogs.LeftStick)
                    {
                        pair.Value.Invoke(GamePadAnalogs.LeftStick,
                            newGamePad4.ThumbSticks.Left.X, newGamePad4.ThumbSticks.Left.Y, PlayerIndex.Four);
                    }
                }
            }

            if (newGamePad1.ThumbSticks.Right.X != m_oldGamePad.ThumbSticks.Right.X ||
                newGamePad1.ThumbSticks.Right.Y != m_oldGamePad.ThumbSticks.Right.Y)
            {
                foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in m_gamePadAnalogBindings)
                {
                    if (pair.Key == GamePadAnalogs.RightStick)
                    {
                        pair.Value.Invoke(GamePadAnalogs.RightStick,
                            newGamePad1.ThumbSticks.Right.X, newGamePad1.ThumbSticks.Right.Y, PlayerIndex.One);
                    }
                }
            }

            if (newGamePad2.ThumbSticks.Right.X != m_oldGamePad.ThumbSticks.Right.X ||
                newGamePad2.ThumbSticks.Right.Y != m_oldGamePad.ThumbSticks.Right.Y)
            {
                foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in m_gamePadAnalogBindings)
                {
                    if (pair.Key == GamePadAnalogs.RightStick)
                    {
                        pair.Value.Invoke(GamePadAnalogs.RightStick,
                            newGamePad2.ThumbSticks.Right.X, newGamePad2.ThumbSticks.Right.Y, PlayerIndex.Two);
                    }
                }
            }

            if (newGamePad3.ThumbSticks.Right.X != m_oldGamePad.ThumbSticks.Right.X ||
                newGamePad3.ThumbSticks.Right.Y != m_oldGamePad.ThumbSticks.Right.Y)
            {
                foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in m_gamePadAnalogBindings)
                {
                    if (pair.Key == GamePadAnalogs.RightStick)
                    {
                        pair.Value.Invoke(GamePadAnalogs.RightStick,
                            newGamePad3.ThumbSticks.Right.X, newGamePad3.ThumbSticks.Right.Y, PlayerIndex.Three);
                    }
                }
            }

            if (newGamePad4.ThumbSticks.Right.X != m_oldGamePad.ThumbSticks.Right.X ||
                newGamePad4.ThumbSticks.Right.Y != m_oldGamePad.ThumbSticks.Right.Y)
            {
                foreach (KeyValuePair<GamePadAnalogs, GamePadInputAction> pair in m_gamePadAnalogBindings)
                {
                    if (pair.Key == GamePadAnalogs.RightStick)
                    {
                        pair.Value.Invoke(GamePadAnalogs.RightStick,
                            newGamePad4.ThumbSticks.Right.X, newGamePad4.ThumbSticks.Right.Y, PlayerIndex.Four);
                    }
                }
            }

            // -------------ADDED FOR MORE FUNCTIONALITY--------------
            CheckLogicStates(newKeyboard, newMouse, newGamePad1, newGamePad2, newGamePad3, newGamePad4);
            // -------------END OF ADDED FUNCTIONALITY----------------

            m_oldGamePad = newGamePad1;
            m_oldGamePad2 = newGamePad2;
            m_oldGamePad3 = newGamePad3;
            m_oldGamePad4 = newGamePad4;

            m_oldKeyboard = newKeyboard;
            m_oldMouse = newMouse;
        }
        // ZOMG, HAXXORZ!
        // ------------------ADDED FOR MORE FUNCTIONALITY-------------------
        private void CheckLogicStates(KeyboardState newKeyboard, MouseState newMouse, GamePadState newGamePad1,
                                     GamePadState newGamePad2, GamePadState newGamePad3, GamePadState newGamePad4)
        {
            // Cycles through all the 'modified logic states' and determines whether each binding's
            // condition has been met (whether a button is being held, pressed, released, or hasn't been touched.)
            foreach (KeyDelegateLogic binding in m_keyboardLogicBindings)
            {
                bool isDown = newKeyboard.IsKeyDown(binding.key);
                bool wasDown = m_oldKeyboard.IsKeyDown(binding.key);

                if(binding.logic == ButtonStateLogic.Pressed)
                {
                    if (isDown && !wasDown)
                    {
                        binding.action.Invoke(binding.key, binding.logic);
                    }
                }
                else if (binding.logic == ButtonStateLogic.Released)
                {
                    if (!isDown && wasDown)
                    {
                        binding.action.Invoke(binding.key, binding.logic);
                    }
                }
                else if (binding.logic == ButtonStateLogic.Held)
                {
                    if (isDown && wasDown)
                    {
                        binding.action.Invoke(binding.key, binding.logic);
                    }
                }
                else if (binding.logic == ButtonStateLogic.NotPressed)
                {
                    if (!isDown && !wasDown)
                    {
                        binding.action.Invoke(binding.key, binding.logic);
                    }
                }
            }

            // Cycles through the 'modified logic states' and determines whether each binding's
            // condition has been met
            foreach (ButtonDelegateLogic binding in m_gamePadLogicBindings)
            {
                if(binding.logic == ButtonStateLogic.Pressed)
                {
                    if (newGamePad1.IsButtonDown(binding.button) && newGamePad1.IsButtonUp(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.One);
                    }
                    if (newGamePad2.IsButtonDown(binding.button) && newGamePad2.IsButtonUp(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Two);
                    }
                    if (newGamePad3.IsButtonDown(binding.button) && newGamePad3.IsButtonUp(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Three);
                    }
                    if (newGamePad4.IsButtonDown(binding.button) && newGamePad4.IsButtonUp(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Four);
                    }
                }
                else if (binding.logic == ButtonStateLogic.Released)
                {
                    if (newGamePad1.IsButtonUp(binding.button) && newGamePad1.IsButtonDown(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.One);
                    }
                    if (newGamePad2.IsButtonUp(binding.button) && newGamePad2.IsButtonDown(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Two);
                    }
                    if (newGamePad3.IsButtonUp(binding.button) && newGamePad3.IsButtonDown(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Three);
                    }
                    if (newGamePad4.IsButtonUp(binding.button) && newGamePad4.IsButtonDown(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Four);
                    }
                }
                else if (binding.logic == ButtonStateLogic.Held)
                {
                    if (newGamePad1.IsButtonDown(binding.button) && newGamePad1.IsButtonDown(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.One);
                    }
                    if (newGamePad2.IsButtonDown(binding.button) && newGamePad2.IsButtonDown(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Two);
                    }
                    if (newGamePad3.IsButtonDown(binding.button) && newGamePad3.IsButtonDown(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Three);
                    }
                    if (newGamePad4.IsButtonDown(binding.button) && newGamePad4.IsButtonDown(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Four);
                    }
                }
                else if (binding.logic == ButtonStateLogic.NotPressed)
                {
                    if (newGamePad1.IsButtonUp(binding.button) && newGamePad1.IsButtonUp(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.One);
                    }
                    if (newGamePad2.IsButtonUp(binding.button) && newGamePad2.IsButtonUp(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Two);
                    }
                    if (newGamePad3.IsButtonUp(binding.button) && newGamePad3.IsButtonUp(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Three);
                    }
                    if (newGamePad4.IsButtonUp(binding.button) && newGamePad4.IsButtonUp(binding.button))
                    {
                        binding.action.Invoke(binding.button, binding.logic, PlayerIndex.Four);
                    }
                }
            }

            // Determines which way the mouse has moved and invokes the appropriate methods.
            foreach (MouseMovementDelegateLogic binding in m_mouseMovementBindings)
            {
                if (binding.movement == AnalogMovements.MoveUp)
                {
                    if (newMouse.Y < m_oldMouse.Y)
                    {
                        binding.action.Invoke(binding.movement, newMouse.X, newMouse.Y);
                    }
                }
                else if (binding.movement == AnalogMovements.MoveDown)
                {
                    if (newMouse.Y > m_oldMouse.Y)
                    {
                        binding.action.Invoke(binding.movement, newMouse.X, newMouse.Y);
                    }
                }
                else if (binding.movement == AnalogMovements.MoveLeft)
                {
                    if (newMouse.X < m_oldMouse.X)
                    {
                        binding.action.Invoke(binding.movement, newMouse.X, newMouse.Y);
                    }
                }
                else if (binding.movement == AnalogMovements.MoveRight)
                {
                    if (newMouse.X > m_oldMouse.X)
                    {
                        binding.action.Invoke(binding.movement, newMouse.X, newMouse.Y);
                    }
                }
            }

            // Orchestrates all the logic needed for determining what joystick has been pressed in 
            // which direction on which controller and executing the bound method accordingly.
            foreach (JoystickMovementDelegateLogic binding in m_gamePadMovementBindings)
            {
                if (binding.joystick == GamePadAnalogs.LeftStick)
                {
                    if (binding.movement == AnalogMovements.MoveUp)
                    {
                        if (newGamePad1.ThumbSticks.Left.Y < m_oldGamePad.ThumbSticks.Left.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad1.ThumbSticks.Left.X,
                                                  newGamePad1.ThumbSticks.Left.Y, PlayerIndex.One);
                        }
                        if (newGamePad2.ThumbSticks.Left.Y < m_oldGamePad2.ThumbSticks.Left.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad2.ThumbSticks.Left.X,
                                                  newGamePad2.ThumbSticks.Left.Y, PlayerIndex.Two);
                        }
                        if (newGamePad3.ThumbSticks.Left.Y < m_oldGamePad3.ThumbSticks.Left.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad3.ThumbSticks.Left.X,
                                                  newGamePad3.ThumbSticks.Left.Y, PlayerIndex.Three);
                        }
                        if (newGamePad4.ThumbSticks.Left.Y < m_oldGamePad4.ThumbSticks.Left.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad4.ThumbSticks.Left.X,
                                                  newGamePad4.ThumbSticks.Left.Y, PlayerIndex.Four);
                        }
                    }
                    else if (binding.movement == AnalogMovements.MoveDown)
                    {
                        if (newGamePad1.ThumbSticks.Left.Y > m_oldGamePad.ThumbSticks.Left.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad1.ThumbSticks.Left.X,
                                                  newGamePad1.ThumbSticks.Left.Y, PlayerIndex.One);
                        }
                        if (newGamePad2.ThumbSticks.Left.Y > m_oldGamePad2.ThumbSticks.Left.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad2.ThumbSticks.Left.X,
                                                  newGamePad2.ThumbSticks.Left.Y, PlayerIndex.Two);
                        }
                        if (newGamePad3.ThumbSticks.Left.Y > m_oldGamePad3.ThumbSticks.Left.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad3.ThumbSticks.Left.X,
                                                  newGamePad3.ThumbSticks.Left.Y, PlayerIndex.Three);
                        }
                        if (newGamePad4.ThumbSticks.Left.Y > m_oldGamePad4.ThumbSticks.Left.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad4.ThumbSticks.Left.X,
                                                  newGamePad4.ThumbSticks.Left.Y, PlayerIndex.Four);
                        }
                    }
                    else if (binding.movement == AnalogMovements.MoveLeft)
                    {
                        if (newGamePad1.ThumbSticks.Left.X < m_oldGamePad.ThumbSticks.Left.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad1.ThumbSticks.Left.X,
                                                  newGamePad1.ThumbSticks.Left.Y, PlayerIndex.One);
                        }
                        if (newGamePad2.ThumbSticks.Left.X < m_oldGamePad2.ThumbSticks.Left.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad2.ThumbSticks.Left.X,
                                                  newGamePad2.ThumbSticks.Left.Y, PlayerIndex.Two);
                        }
                        if (newGamePad3.ThumbSticks.Left.X < m_oldGamePad3.ThumbSticks.Left.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad3.ThumbSticks.Left.X,
                                                  newGamePad3.ThumbSticks.Left.Y, PlayerIndex.Three);
                        }
                        if (newGamePad4.ThumbSticks.Left.X < m_oldGamePad4.ThumbSticks.Left.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad4.ThumbSticks.Left.X,
                                                  newGamePad4.ThumbSticks.Left.Y, PlayerIndex.Four);
                        }
                    }
                    else if (binding.movement == AnalogMovements.MoveRight)
                    {
                        if (newGamePad1.ThumbSticks.Left.X > m_oldGamePad.ThumbSticks.Left.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad1.ThumbSticks.Left.X,
                                                  newGamePad1.ThumbSticks.Left.Y, PlayerIndex.One);
                        }
                        if (newGamePad2.ThumbSticks.Left.X > m_oldGamePad2.ThumbSticks.Left.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad2.ThumbSticks.Left.X,
                                                  newGamePad2.ThumbSticks.Left.Y, PlayerIndex.Two);
                        }
                        if (newGamePad3.ThumbSticks.Left.X > m_oldGamePad3.ThumbSticks.Left.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad3.ThumbSticks.Left.X,
                                                  newGamePad3.ThumbSticks.Left.Y, PlayerIndex.Three);
                        }
                        if (newGamePad4.ThumbSticks.Left.X > m_oldGamePad4.ThumbSticks.Left.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad4.ThumbSticks.Left.X,
                                                  newGamePad4.ThumbSticks.Left.Y, PlayerIndex.Four);
                        }
                    }
                }
                else if (binding.joystick == GamePadAnalogs.RightStick)
                {
                    if (binding.movement == AnalogMovements.MoveUp)
                    {
                        if (newGamePad1.ThumbSticks.Right.Y < m_oldGamePad.ThumbSticks.Right.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad1.ThumbSticks.Left.X,
                                                  newGamePad1.ThumbSticks.Left.Y, PlayerIndex.One);
                        }
                        if (newGamePad2.ThumbSticks.Right.Y < m_oldGamePad2.ThumbSticks.Right.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad2.ThumbSticks.Left.X,
                                                  newGamePad2.ThumbSticks.Left.Y, PlayerIndex.Two);
                        }
                        if (newGamePad3.ThumbSticks.Right.Y < m_oldGamePad3.ThumbSticks.Right.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad3.ThumbSticks.Left.X,
                                                  newGamePad3.ThumbSticks.Left.Y, PlayerIndex.Three);
                        }
                        if (newGamePad4.ThumbSticks.Right.Y < m_oldGamePad4.ThumbSticks.Right.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad4.ThumbSticks.Left.X,
                                                  newGamePad4.ThumbSticks.Left.Y, PlayerIndex.Four);
                        }
                    }
                    else if (binding.movement == AnalogMovements.MoveDown)
                    {
                        if (newGamePad1.ThumbSticks.Right.Y > m_oldGamePad.ThumbSticks.Right.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad1.ThumbSticks.Left.X,
                                                  newGamePad1.ThumbSticks.Left.Y, PlayerIndex.One);
                        }
                        if (newGamePad2.ThumbSticks.Right.Y > m_oldGamePad2.ThumbSticks.Right.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad2.ThumbSticks.Left.X,
                                                  newGamePad2.ThumbSticks.Left.Y, PlayerIndex.Two);
                        }
                        if (newGamePad3.ThumbSticks.Right.Y > m_oldGamePad3.ThumbSticks.Right.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad3.ThumbSticks.Left.X,
                                                  newGamePad3.ThumbSticks.Left.Y, PlayerIndex.Three);
                        }
                        if (newGamePad4.ThumbSticks.Right.Y > m_oldGamePad4.ThumbSticks.Right.Y)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad4.ThumbSticks.Left.X,
                                                  newGamePad4.ThumbSticks.Left.Y, PlayerIndex.Four);
                        }
                    }
                    else if (binding.movement == AnalogMovements.MoveLeft)
                    {
                        if (newGamePad1.ThumbSticks.Right.X < m_oldGamePad.ThumbSticks.Right.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad1.ThumbSticks.Left.X,
                                                  newGamePad1.ThumbSticks.Left.Y, PlayerIndex.One);
                        }
                        if (newGamePad2.ThumbSticks.Right.X < m_oldGamePad2.ThumbSticks.Right.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad2.ThumbSticks.Left.X,
                                                  newGamePad2.ThumbSticks.Left.Y, PlayerIndex.Two);
                        }
                        if (newGamePad3.ThumbSticks.Right.X < m_oldGamePad3.ThumbSticks.Right.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad3.ThumbSticks.Left.X,
                                                  newGamePad3.ThumbSticks.Left.Y, PlayerIndex.Three);
                        }
                        if (newGamePad4.ThumbSticks.Right.X < m_oldGamePad4.ThumbSticks.Right.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad4.ThumbSticks.Left.X,
                                                  newGamePad4.ThumbSticks.Left.Y, PlayerIndex.Four);
                        }
                    }
                    else if (binding.movement == AnalogMovements.MoveRight)
                    {
                        if (newGamePad1.ThumbSticks.Right.X > m_oldGamePad.ThumbSticks.Right.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad1.ThumbSticks.Left.X,
                                                  newGamePad1.ThumbSticks.Left.Y, PlayerIndex.One);
                        }
                        if (newGamePad2.ThumbSticks.Right.X > m_oldGamePad2.ThumbSticks.Right.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad2.ThumbSticks.Left.X,
                                                  newGamePad2.ThumbSticks.Left.Y, PlayerIndex.Two);
                        }
                        if (newGamePad3.ThumbSticks.Right.X > m_oldGamePad3.ThumbSticks.Right.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad3.ThumbSticks.Left.X,
                                                  newGamePad3.ThumbSticks.Left.Y, PlayerIndex.Three);
                        }
                        if (newGamePad4.ThumbSticks.Right.X > m_oldGamePad4.ThumbSticks.Right.X)
                        {
                            binding.action.Invoke(binding.joystick, binding.movement, newGamePad4.ThumbSticks.Left.X,
                                                  newGamePad4.ThumbSticks.Left.Y, PlayerIndex.Four);
                        }
                    }
                }
            }
        }
        // -----------------END OF ADDED FUNCTIONALITY-------------------
        #endregion
    }
}